package com.bps.zzant.json;



import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.bps.zzant.controller.GarmentOrderController;
import com.bps.zzant.dao.CustomerDAO;
import com.bps.zzant.model.Customer;
import com.bps.zzant.model.ArtFile;
import com.bps.zzant.model.OrderForm;
import com.bps.zzant.model.OrderGarment;
import com.bps.zzant.model.OrderGarmentItem;
import com.bps.zzant.model.Payment;
import com.bps.zzant.model.PaymentFooter;
import com.bps.zzant.model.ToDo;
import com.bps.zzant.services.CustomerService;
import com.bps.zzant.services.OrderService;
import com.bps.zzant.services.PaymentService;




@Controller
public class OrderJSON {
	
	   private static final Logger logger = LoggerFactory.getLogger(OrderJSON.class);
	   
		@Autowired
		private OrderService orderService;
		
		@Autowired
		private PaymentService paymentService;
	   

		@Autowired
		private CustomerService customerService;
		
		public void setOrderService(OrderService orderService) {
			this.orderService = orderService;
		}

	    public void setPaymentService(PaymentService paymentService) {
			this.paymentService = paymentService;
		}
	   	   
		public void setCustomerService(CustomerService customerService) {
			this.customerService = customerService;
		}

	@InitBinder
	   public void initBinder(WebDataBinder binder) {
	            SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
	            dateFormat.setLenient(false);
	            binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
          
	          //  binder.registerCustomEditor(Integer.TYPE, new CustomerDoubleEditor());
	   }
	
/*	   private static class CustomerDoubleEditor extends PropertyEditorSupport{    
		   public void setAsText(String str) { 
		       if(str == null || str.equals("")) 
		           setValue(0); 
		       else 
		        setValue(Double.parseDouble(str)); 
		  } 
		}*/
		
		@RequestMapping(value = "getOrderItemsInSession.json", method = RequestMethod.POST)
		public Map getOrderItemsInSession(HttpServletRequest request, HttpServletResponse response) {
			
			logger.info(" +++++++++in getOrderItemsInSession.json: Order.");
			
			Map<String, Object> map = new HashMap<String, Object>();
			BigDecimal totalPrice = new BigDecimal("0.00");
			
			HttpSession session =  request.getSession();
			List<OrderGarmentItem> orderGarmentItemsList = (List<OrderGarmentItem>) session.getAttribute("ORDER_ITEMS");
			
			if(orderGarmentItemsList!=null){
				for(Iterator i = orderGarmentItemsList.iterator(); i.hasNext();){					
					OrderGarmentItem item = (OrderGarmentItem)i.next();
					totalPrice = item.getSubTotal().add(totalPrice);
					
				}				
				
			}
			map.put("totalPrice", totalPrice);
			
			map.put("rows", orderGarmentItemsList);
			return map;
			 
		}
		
		
		@RequestMapping(value = "clearOrderItems.json", method = RequestMethod.POST)
		public Map clearOrderItemsInSession(HttpServletRequest request, HttpServletResponse response) {
			Map<String, Object> map = new HashMap<String, Object>();
			request.getSession().setAttribute("ORDER_ITEMS", null);
			map.put("success", new Boolean("true"));
			return map; 
		}
		
		
		@RequestMapping(value = "saveOrderItem.json", method = RequestMethod.POST)
		public Map saveOrderItemInSession(@Valid OrderGarmentItem orderGarmentItem, BindingResult errors, HttpServletRequest request){

			Map<String, Object> map = new HashMap<String, Object>();
			HttpSession session =  request.getSession();
			
			
			logger.info(" +++++++++in saveOrderItemInSession.json+++ Item No.:"+orderGarmentItem.getStyleNo());
			logger.info(" +++++++++in saveOrderItemInSession.json+++ description:"+orderGarmentItem.getDesc());
			logger.info(" +++++++++in saveOrderItemInSession.json+++ unitPrice:"+orderGarmentItem.getUnitPrice());
			
						// List productList = productService.getProductByStyleNo("29");
			// logger.info(" ++++ product size: " + productList.size());
			
			if (errors.hasErrors()) {
				logger.info(" +++++++++in saveOrderItemInSession.json+++ has errors " + errors.toString());
				//handle the binding errors
			}else{
				List<OrderGarmentItem> orderGarmentItemsList = (List<OrderGarmentItem>) session.getAttribute("ORDER_ITEMS");
				
				// orderGarmentItem.setLineNo(orderGarmentItemsList==null?1:orderGarmentItemsList.size()+1);
				orderGarmentItem.setSubTotal(orderGarmentItem.getUnitPrice().multiply(new BigDecimal(orderGarmentItem.getQty())));
				
				if(orderGarmentItemsList==null){
					orderGarmentItemsList = new ArrayList<OrderGarmentItem>();
					orderGarmentItemsList.add(orderGarmentItem);
					
				}else{
					orderGarmentItemsList.add(orderGarmentItem);
					
				}				
				
				
				session.setAttribute("ORDER_ITEMS", orderGarmentItemsList);
				map.put("success", new Boolean("true"));

			}
			return map;
		}
		
		@RequestMapping(value = "removeOrderItem.json", method = RequestMethod.POST)
		
		public Map removeOrderItemInSession(@Valid OrderGarmentItem orderGarmentItem, BindingResult errors, HttpServletRequest request) {
			logger.info(" +++++++++in OrderJSON.removeOrderItemInSession. The lineNo is:"+request.getParameter("lineNo"));
			
			int lineNo = Integer.parseInt(request.getParameter("lineNo"));
			
			Map<String, Object> map = new HashMap<String, Object>();
			HttpSession session =  request.getSession();
			List<OrderGarmentItem> orderGarmentItemsList = (List<OrderGarmentItem>) session.getAttribute("ORDER_ITEMS");
			
			orderGarmentItemsList.remove(lineNo);
		
			map.put("success", new Boolean("true"));
			return map; 
		}
		
		@RequestMapping(value = "editOrderItem.json", method = RequestMethod.POST)
		
		public Map editOrderItemInSession(@Valid OrderGarmentItem orderGarmentItem, BindingResult errors, HttpServletRequest request) {
			
			logger.info(" +++++++++in OrderJSON.removeOrderItemInSession. Parameter The lineNo is:"+request.getParameter("lineNo"));
			logger.info(" +++++++++orderItem is:" + orderGarmentItem.getQty() +"|" + orderGarmentItem.getUnitPrice());
			
			Map<String, Object> map = new HashMap<String, Object>();
			HttpSession session =  request.getSession();
			
			orderGarmentItem.setSubTotal(orderGarmentItem.getUnitPrice().multiply(new BigDecimal(orderGarmentItem.getQty())));
			
			List<OrderGarmentItem> orderGarmentItemsList = (List<OrderGarmentItem>) session.getAttribute("ORDER_ITEMS");
						
			int lineNo = Integer.parseInt(request.getParameter("lineNo"));
			orderGarmentItemsList.set(lineNo, orderGarmentItem);

			map.put("success", new Boolean("true"));
			
			return map; 
		}
		
		// this method save the Order into database
		@RequestMapping(value = "saveOrder.json", method = RequestMethod.POST)
		public Map saveOrder(@Valid OrderForm orderForm, BindingResult errors, HttpServletRequest request){

			Map<String, Object> map = new HashMap<String, Object>();
			
			HttpSession session =  request.getSession();
			List<OrderGarmentItem> orderGarmentItemsList = (List<OrderGarmentItem>) session.getAttribute("ORDER_ITEMS");
			
			List<Payment> paymentList = new ArrayList<Payment>();
			logger.info(" +++++++++in OrderJSON.saveOrder Date Purchase:" + orderForm.getDatePurchased());
			
			// logger.info("+++++++ order status is : " + orderForm.getOrderStatus());
			if(orderGarmentItemsList==null || orderGarmentItemsList.size()==0){
				
				map.put("msg", "You haven't enter any items yet. The order is NOT saved.");
				map.put("success", new Boolean("false"));
			}else{
				
				OrderGarment order = new OrderGarment(orderForm);
				logger.info(" +++++++++in OrderJSON.saveOrder 1");
				//if the customer is not an existing customer
				if(order.getCustomerId()==0){
					Customer customer = new Customer(order);
					// logger.info(" +++++++++in save customer . before Customer Id:"+customer.getId());
					customerService.saveCustomer(customer);
					// logger.info(" +++++++++in save customer. after Customer Id:"+customer.getId());
					order.setCustomerId(customer.getId());
				}
				
				logger.info(" +++++++++in OrderJSON.saveOrder 1. "+ order.toString());
				logger.info(" +++++++++in OrderJSON.saveOrder 2. "+ order.getCustomerId());				
				for(Iterator i = orderGarmentItemsList.iterator(); i.hasNext();){					
					OrderGarmentItem item = (OrderGarmentItem)i.next();
					item.setOrder(order);
				}
				
				order.setGarmentItems(orderGarmentItemsList);
				

								
				// logger.info(" +++++++++in OrderJSON.saveOrder before save. Item size:" + order.getGarmentItems().size());
				// order.addOrderGarmentItems(orderGarmentItemsList);
				// logger.info(" +++++++++in OrderJSON.saveOrder before save the order id= "+ order.getOrderId());
				
				if(order.getOrderId()>0){					
					// *********** if it is edit order, get the original purchase date, and set it in the order *********
/*					OrderGarment currentOrder = orderService.getOrderById(order.getOrderId());					
					order.setDatePurchased(currentOrder.getDatePurchased());*/
					//*************       end of set original purchase date                                     **********
					logger.info(" +++++++++in OrderJSON.saveOrder Date Purchase:" + order.getDatePurchased());
					order.setLastModified(new Date());
					
					List<Payment> originalPaymentList = paymentService.getPaymentsByOrderId(order.getOrderId());
					
					
					/* Payment addlPayment = new Payment(orderForm);
					
					addlPayment.setOrder(order);
					paymentList.add(addlPayment);*/
					
					order.setPayments(originalPaymentList);
					orderService.updateGarmentOrder(order);
				}else{
					// set PAYMENT to the OrderGarment domain object
					Payment initDownPayment = new Payment(orderForm);
					initDownPayment.setOrder(order);
					List<Payment> payments = new ArrayList<Payment>();
					payments.add(initDownPayment);
					order.setPayments(payments);
					// end of set PAYMENT
					
					order.setDatePurchased(new Date());
					orderService.saveGarmentOrder(order);
				}
				
				logger.info(" +++++++++in OrderJSON.saveOrder after save the order id= "+ order.getOrderId());
				map.put("success", new Boolean("true"));
				map.put("orderId", order.getOrderId());
				map.put("purchaseDate", new SimpleDateFormat("MM/dd/yyyy hh:mm aaa").format(order.getDatePurchased()) );
			}
			
			return map; 
			
		}

		@RequestMapping(value = "getOrderList.json", method = RequestMethod.POST)
		public Map getOrderList(HttpServletRequest request, HttpServletResponse response) {
			
			logger.info(" +++SSSSS++++++in getOrderList.json: status | customerName | fromDate | toDate:"+ request.getParameter("status")+"|"+ request.getParameter("customerName")+"|"+request.getParameter("fromDate")+"|"+request.getParameter("toDate"));
						
			Map<String, Object> map = new HashMap<String, Object>();
			List<OrderGarment> orderList;
			String status = request.getParameter("status")==null?"approved":request.getParameter("status");
			Date fromDate = new Date(System.currentTimeMillis()-15*24*60*60*1000);
			Date toDate = new Date(System.currentTimeMillis()+15*24*60*60*1000);
			
			
			String customerName = 	request.getParameter("customerName");		
			try {
				fromDate = StringUtils.hasText(request.getParameter("fromDate"))?new SimpleDateFormat("M/d/yyyy", Locale.US).parse(request.getParameter("fromDate")):fromDate;
				toDate = StringUtils.hasText(request.getParameter("toDate"))?new SimpleDateFormat("M/d/yyyy", Locale.US).parse(request.getParameter("toDate")):toDate;
			} catch (ParseException e) {
			
				map.put("success", new Boolean("false"));
				map.put("msg", "Date format must be mm/dd/yyyy.");
				// e.printStackTrace();
				return map;
			}  
			
//			logger.info("--------fromDate=" + fromDate);
//			logger.info("--------toDate=" + toDate);
			
			if(StringUtils.hasText(customerName) && StringUtils.hasText(request.getParameter("fromDate")) && StringUtils.hasText(request.getParameter("toDate"))){
				orderList = orderService.getOrderList(customerName, status, fromDate, toDate);
				
			}else if(!StringUtils.hasText(request.getParameter("fromDate")) && !StringUtils.hasText(request.getParameter("toDate"))){
				orderList = orderService.getOrderList(customerName, status);
			}else{				
				orderList = orderService.getOrderList(status, fromDate, toDate);
			}
			//  List<ToDo> toDoList = toDoService.getToDoList(owner, "open");
			 map.put("rows", orderList);
			 
			 return map;
			 
		}
		
		@RequestMapping(value = "getAllOrderList.json", method = RequestMethod.POST)
		public Map getAllOrderList(HttpServletRequest request, HttpServletResponse response) {
			
			logger.info(" +++++++in getAllOrderList.json: order number | customerName :"+ request.getParameter("orderId")+"|"+ request.getParameter("customerName"));
						
			Map<String, Object> map = new HashMap<String, Object>();
			List<OrderGarment> orderList;
						
			String customerName = 	request.getParameter("customerName");		
			String orderId = request.getParameter("orderId");
			
			map.put("success", new Boolean("false"));
			
			if(StringUtils.hasText(orderId)){
				 OrderGarment order = orderService.getOrderById(Integer.parseInt(orderId.trim()));
				 orderList = new ArrayList<OrderGarment>();
				 orderList.add(order);
			}else if(StringUtils.hasText(customerName) ){
				orderList = orderService.getOrderList("%"+customerName.trim()+"%");				
			}else{
				orderList = orderService.getOrderList("%");
			}
			//  List<ToDo> toDoList = toDoService.getToDoList(owner, "open");
			 map.put("rows", orderList);
			 
			 return map;
			 
		}
		
		@RequestMapping(value = "pickupOrder.json", method = RequestMethod.POST)
		public Map pickupOrder(HttpServletRequest request, HttpServletResponse response){
			
			String isOrderFinished = request.getParameter("isFinished");
			String isOrderApproved = request.getParameter("isApproved");
			String hasPayment = request.getParameter("haspayment");
			String paymentAmount = request.getParameter("paymentAmount")==null?"0":request.getParameter("paymentAmount").replace(",", "").replace("$", "");
			String paymentMethod = request.getParameter("paymentMethod")==null?"":request.getParameter("paymentMethod");
			
			logger.info(" +++++++++in pickupOrder.json: isOrderApproved:"+ isOrderApproved);
			logger.info(" +++++++++in pickupOrder.json: isOrderFinished:"+ isOrderFinished);
			logger.info(" +++++++++in pickupOrder.json: hasPayment:"+ hasPayment);
			logger.info(" +++++++++in pickupOrder.json: paymentAmount:"+ paymentAmount);
			logger.info(" +++++++++in pickupOrder.json: paymentMethod:"+ paymentMethod);
			
			int orderId = Integer.parseInt(request.getParameter("orderId"));
			
			Map<String, Object> map = new HashMap<String, Object>();
			
			OrderGarment order =  orderService.getOrderById(orderId);
						
			if("yes".equals(isOrderFinished)){
				order.setOrdersStatus("finished");
			}else if("yes".equals(isOrderApproved)){
				order.setOrdersStatus("approved");
			}

			
			if(!StringUtils.hasText(hasPayment)){ //if hasPayment is not selected
				map.put("success", new Boolean("false"));
				map.put("msg", "Please select With Payment? Yes or No?");
			}else if("yes".equals(hasPayment) && (!StringUtils.hasText(paymentAmount) || !StringUtils.hasText(paymentMethod))){
				map.put("success", new Boolean("false"));
				map.put("msg", "When Payment is Yes, Payment Method and Payment Amount cannot be empty.");
			}else if ("yes".equals(hasPayment) && StringUtils.hasText(paymentAmount) && StringUtils.hasText(paymentMethod)){ // hasPayment is Yes and we know the payment amount, so update the payment info
				String paymentType;
				if("yes".equals(isOrderApproved)){
					paymentType = "initDown";
				}else if(order.getBalance().equals(new BigDecimal(paymentAmount))){
					paymentType = "final";
				}else{
					paymentType = "addl";
				}
								
				Payment newPayment = new Payment(paymentMethod, new BigDecimal(paymentAmount), paymentType);
				newPayment.setOrder(order);
				
				if("yes".equals(isOrderApproved) && "yes".equals(hasPayment)){
					
					//if order just get approved, remove the original initDown payment method							
					for(Iterator<Payment> it = order.getPayments().iterator(); it.hasNext();){					
						Payment payment = (Payment)it.next();
						if("initDown".equals(payment.getPaymentType())){
							it.remove();
						}
						
					}		
							
					
					
				}
				order.getPayments().add(newPayment);
			
				orderService.updateGarmentOrder(order);
				map.put("success", new Boolean("true"));
				
			}else { 
				logger.info("------------------ AAAAAAAAAAAAAAAA = " + order.getOrdersStatus());
				orderService.updateGarmentOrder(order);
				map.put("success", new Boolean("true"));
			}
			
			
			
			return map;
		}
		
		
		@RequestMapping(value = "getPaymentsByOrderId.json", method = RequestMethod.POST)
		public Map getPaymentsByOrderId(HttpServletRequest request, HttpServletResponse response) {
			
			logger.info(" +++++++++in getPaymentsByOrderId.json: orderId:" +  request.getParameter("orderId"));
						
			Map<String, Object> map = new HashMap<String, Object>();
			List<PaymentFooter> footer = new ArrayList<PaymentFooter>();
			String orderId = request.getParameter("orderId");
			
			if(!StringUtils.hasText(orderId)){
				return map;
			}
			  OrderGarment order = orderService.getOrderById(Integer.parseInt(orderId));
			  List<Payment> paymentList = paymentService.getPaymentsByOrderId(Integer.parseInt(orderId));
			  
			  PaymentFooter invoiceTotal = new PaymentFooter("<div style='font-weight: bold; color: #686A6D;'>Total Price:</div>", order.getTotalPrice());
			  PaymentFooter subTotal = new PaymentFooter("<div style='font-weight: bold; color: #686A6D;'>Total Payment:</div>", order.getTotalPayment());
			  PaymentFooter balance = new PaymentFooter("<div style='font-weight: bold; color: #686A6D;'>Balance:</div>", order.getTotalPrice().subtract(order.getTotalPayment()) );
			  footer.add(invoiceTotal);
			  footer.add(subTotal);
			  footer.add(balance);
			 map.put("rows", paymentList);
			 map.put("footer", footer);
			 
			 return map;
			 
		}
		
		@RequestMapping(value = "getOrderItemsByOrderId.json", method = RequestMethod.GET)
		public Map getOrderItemsByOrderId(HttpServletRequest request, HttpServletResponse response) {
			
			logger.info(" +++++++++in getOrderItemsByOrderId.json: Order." + request.getParameter("orderId"));
			int orderId = Integer.parseInt(request.getParameter("orderId"));
			
			Map<String, Object> map = new HashMap<String, Object>();
			
			OrderGarment order = orderService.getOrderById(orderId);
			
			map.put("rows", order.getGarmentItems());
			return map;
			 
		}
		
		
}
